package main

import (
	"fmt"
	"reflect"
)

// 演示普通类型反射机制
func reflectTest01(b interface{}) {
	// 需求：通过反射获取的传入的变量的type，kind，值
	// 1、先获取到reflect.Type
	rType := reflect.TypeOf(b)
	fmt.Println("rType:", rType)

	//2、获取到reflect.Value
	rVal := reflect.ValueOf(b)

	n2 := 2 + rVal.Int()
	fmt.Println("n2:", n2)
	fmt.Printf("rVal=%v rVal Type=%T\n", rVal, rVal)

	// 下面将rVal 转成interface{}
	iV := rVal.Interface()
	num2 := iV.(int) //类型断言
	fmt.Println("num2:", num2)
}

type Student struct {
	Name string
	Age  int
}

// 演示结构体反射机制
func reflectTest02(b interface{}) {
	// 需求：通过反射获取的传入的结构体变量的type，kind，值
	// 1、先获取到reflect.Type
	rType := reflect.TypeOf(b)
	fmt.Println("rType:", rType)

	//2、获取到reflect.Value
	rVal := reflect.ValueOf(b)

	//n2 := 2 + rVal.Int()
	//fmt.Println("n2:", n2)
	//fmt.Printf("rVal=%v rVal Type=%T\n", rVal, rVal)

	// 下面将rVal 转成interface{}
	iV := rVal.Interface()
	fmt.Printf("iV=%v iV Type=%T\n", iV, iV)
	//stu, ok := iV.(Student)
	switch iV.(type) {
	case bool:
	case int:
	case Student:
		stu, _ := iV.(Student)
		fmt.Println(stu.Name)
	default:
		println("类型断言没有此类型")
	}
	//fmt.Println("num2:", num2)
}

// 通过反射修改原有传进来的值
func reflect01(b interface{}) {
	rVal := reflect.ValueOf(b)
	fmt.Printf("rVal的Kind=%v\n", rVal.Kind())

	// Elem返回v持有的接口保管的值的Value封装，或者v持有的指针指向的值的Value封装。
	// 如果v的Kind不是Interface或Ptr会panic；如果v持有的值为nil，会返回Value零值。->panic: reflect: call of reflect.Value.Elem on int Value

	rVal.Elem().SetInt(29)

}

func main() {
	// 定义一个int
	//var num int = 100
	//reflectTest01(num)

	// 定义一个Student的实例
	stu := Student{
		Name: "Naughty",
		Age:  23,
	}
	reflectTest02(stu)

	var num1 = 20
	//reflect01(num1)
	// panic: reflect: call of reflect.Value.Elem on int Value
	reflect01(&num1)

	fmt.Println(num1)
}
